#include "application.h"
#include "resource.h"
#include "renderer.h"

#define BOOST_BIND_ENABLE_STDCALL
#include <boost/bind.hpp>

namespace sol9
{

	application::application(const std::tstring& _title, const sol9::dimension2du _size, WNDPROC _proc)
		: title(_title), size(_size), handle(nullptr), proc(_proc), closed(true), ticktime(0)
	{
		_createWindow();
		ticktime = timer.tick();
	}

	application::~application()
	{
	}

	bool application::run()
	{
		ticktime = timer.time();

		MSG msg;

		while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
		{
			DispatchMessage(&msg);

			if (msg.message == WM_QUIT)
				closed = true;
		}

		return !closed;
	}

	void application::close()
	{
		closed = true;
		PostQuitMessage(0);
	}

	u32 application::tick()
	{
		return ticktime;
	}

	void application::createRenderer()
	{
		if (!handle || closed)
			return;

		render.reset(new renderer);

		hdc_ptr hdc(GetDC(handle), boost::bind(ReleaseDC, handle, _1));

		if (!render->initialize(hdc, size))
			close();
	}

	renderer_ptr application::getRenderer() const
	{
		return render;
	}

	bool application::_createWindow()
	{
		HINSTANCE hInstance = GetModuleHandle(nullptr);

		WNDCLASSEX wcex;
		ZeroMemory(&wcex, sizeof(WNDCLASSEX));
		wcex.cbSize			= sizeof(WNDCLASSEX);
		wcex.style			= CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc	= proc;
		wcex.hInstance		= hInstance;
		wcex.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
		wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
		wcex.hbrBackground	= (HBRUSH)GetStockObject(GRAY_BRUSH);
		wcex.lpszClassName	= title.c_str();

		if (!RegisterClassEx(&wcex))
			return false;

		HWND hWnd = CreateWindow(title.c_str(), title.c_str(), WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

		if (!hWnd)
			return false;

		RECT rect = {0, 0, size.w, size.h};
		AdjustWindowRect(&rect, wcex.style, TRUE);
		SetWindowPos(hWnd, HWND_NOTOPMOST, rect.left, rect.top, rect.right, rect.bottom, SWP_NOMOVE);

		ShowWindow(hWnd, SW_SHOW);
		UpdateWindow(hWnd);

		handle = hWnd;
		closed = false;
		return true;
	}

} // namespace sol9